/*
 * Copyright 2007-2009 Perttu "celeron55" Ahola <celeron55@gmail.com>
 *
 * This file is part of jukumagic.
 *
 * jukumagic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jukumagic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jukumagic.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef BOARDWINDOW_H_
#define BOARDWINDOW_H_

#include <wx/wx.h>
#include "board.h"
#include "jumperwire.h"
#include "footprint.h"
#include "component.h"

enum BoardWindowMouseMode
{
	MODE_INVALID,
	MODE_SELECT,
	MODE_LEFT_SELECT,
	MODE_LEFT_SELECT_RECTANGLE,
	MODE_DOWN_ON_SELECTION,
	MODE_MOVE_SELECTION,
	MODE_MOVE_JUMPER_WIRE_HEAD,
	//MODE_MOVE_JUMPER_WIRE_HEAD_AFTER_ADD,
	//MODE_MOVE_JUMPER_WIRE_HEAD_AFTER_ADD_BOTTOM,
	MODE_MOVE_COMPONENT_HEAD,
	MODE_ADD_JUMPER_WIRE,
	MODE_ADD_JUMPER_WIRE_BOTTOM,
	MODE_ADD_CUT,
	MODE_ADD_NARROWCUT,
	MODE_ADD_RESISTOR,
	MODE_ADD_DIODE,
	MODE_ADD_CERAMIC,
	MODE_DELETE,
	MODE_COUNT
};

extern void GetMouseModeText(BoardWindowMouseMode mode, wxString &text);
extern int GetMouseModeTextMaxLen(wxWindow *w);

class BoardScrolledWindow: public wxScrolledWindow, public BoardChangeHandler
{
private:
	void SetStartValues();

	void CalcNeededSize(int &w, int &h, double scale);
	void UpdateVirtualSize();
	
	void CalcBoardOffsets();
	void DrawSelectRect(int sx, int sy);
	void DrawTempLine(int sx1, int sy1, int sx2, int sy2);
	void CalcSelectionThings();
	void UpdateMoveSelection(int board_x, int board_y);
	void UpdateMoveJumperWireHead(int board_x, int board_y);
	//return true if successful, false if not
	bool Rotate180Selection();
	bool Rotate90Selection();
	//BoardChangeHandler functions
	void ContentsChanged();
	void SelectionChanged();
	
	void UpdateModeStaticText();

	int m_board_padding_log_x;
	int m_board_padding_log_y;
	int m_board_first_hole_log_x;
	int m_board_first_hole_log_y;

	int m_last_px_scroll_x, m_last_px_scroll_y;

	BoardWindowMouseMode m_mousemode;

	int m_left_down_sx, m_left_down_sy;
	int m_left_down_board_x, m_left_down_board_y;
	bool m_holerectangle_drawn;
	
	bool m_drag_hysteresis_exceeded;

	int m_last_mouse_sx, m_last_mouse_sy;
	int m_last_mouse_hx, m_last_mouse_hy;

	int m_zoom_rotation;

	int m_middle_start_scroll_x, m_middle_start_scroll_y;
	int m_middle_start_mouse_wx, m_middle_start_mouse_wy;

	bool m_middle_is_down;
	bool m_middle_drag_triggered;

	//selected objects' coordinates
	int m_so_sx1, m_so_sx2, m_so_sy1, m_so_sy2;
	int m_so_board_x1, m_so_board_y1;
	//size
	int m_so_sw, m_so_sh;
	
	int m_so_move_board_dx, m_so_move_board_dy;
	int m_so_new_board_x1, m_so_new_board_y1;
	int m_so_new_logx1, m_so_new_logy1;
	int m_so_new_sx1, m_so_new_sy1;

	wxBitmap *m_selection_bitmap;
	
	JumperWire *m_selected_jumper_wire;
	//-1 if not selected
	int m_selected_jumper_wire_head;
	BoardPoint m_sjwh_orig_point;

	//add component
	int m_ac_board_x1_centered, m_ac_board_y1_centered;
	int m_ac_board_x2_centered, m_ac_board_y2_centered;
	int m_ac_templine_sx1, m_ac_templine_sy1;
	int m_ac_templine_sx2, m_ac_templine_sy2;
	//bool m_ac_templine_drawn;
	bool m_ac_left_down;

	//move component head
	int m_mch_other_pin_x, m_mch_other_pin_y;
	int m_mch_move_pin_x, m_mch_move_pin_y;
	int m_mch_templine_sx1, m_mch_templine_sy1;
	int m_mch_templine_sx2, m_mch_templine_sy2;
	Component *m_mch_component;
	wxString m_mch_moved_head;

	////
	bool m_keystate_control;
	bool m_keystate_shift;
	//

	double m_scale;

	Board *m_board;

	wxStaticText *m_modestatictext;
public:
	
	BoardScrolledWindow();
	BoardScrolledWindow(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size);
	~BoardScrolledWindow();

	void OnPaint(wxPaintEvent &event);
	void OnEraseBackground(wxEraseEvent &event);
	void OnSize(wxSizeEvent &event);
	void OnLeftDown(wxMouseEvent& event);
	void OnLeftUp(wxMouseEvent& event);
	void OnMiddleDown(wxMouseEvent& event);
	void OnMiddleUp(wxMouseEvent& event);
	void OnMotion(wxMouseEvent& event);
	void OnMouseWheel(wxMouseEvent& event);
	
    void OnChar(wxKeyEvent &event);
    void OnKeyDown(wxKeyEvent &event);
    void OnKeyUp(wxKeyEvent &event);

	void ScrollWindow(int dx, int dy, const wxRect *rect);

	void SetMouseMode(BoardWindowMouseMode newmode);

	void SetModeStaticText(wxStaticText *t);
	void OnBoardSizeOrScale();
	void SetBoard(Board *board);
	void SetScale(double scale);
	double GetScale();
	
	void SupplyFootprint(Footprint *footprint);

	bool GetControlState(){ return m_keystate_control; }
	bool GetShiftState(){ return m_keystate_shift; }

	BoardPoint GetVisibleCenterPos();

private:
	DECLARE_DYNAMIC_CLASS(BoardScrolledWindow)
	DECLARE_EVENT_TABLE()
};

#endif

